package com.ruoyi.base.service.impl;

import com.ruoyi.base.domain.BBank;
import com.ruoyi.base.domain.BPaper;
import com.ruoyi.base.domain.BTopic;
import com.ruoyi.base.mapper.BPaperMapper;
import com.ruoyi.base.service.IBPaperService;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 试卷Service业务层处理
 *
 * @author ruoyi
 * @date 2024-03-24
 */
@Service
public class BPaperServiceImpl implements IBPaperService {
    @Autowired
    private BPaperMapper bPaperMapper;
    @Autowired
    private BTopicServiceImpl topicService;
    @Autowired
    private BBankServiceImpl bBankService;
    @Autowired
    private BTopicServiceImpl bTopicService;

    /**
     * 查询试卷
     *
     * @param paperId 试卷主键
     * @return 试卷
     */
    @Override
    public BPaper selectBPaperByPaperId(Long paperId) {
        return bPaperMapper.selectBPaperByPaperId(paperId);
    }

    /**
     * 查询试卷列表
     *
     * @param bPaper 试卷
     * @return 试卷
     */
    @Override
    public List<BPaper> selectBPaperList(BPaper bPaper) {
        return bPaperMapper.selectBPaperList(bPaper);
    }

    /**
     * 新增试卷
     *
     * @param bPaper 试卷
     * @return 结果
     */
    @Override
    public int insertBPaper(BPaper bPaper) {
        return bPaperMapper.insertBPaper(bPaper);
    }

    /**
     * 修改试卷
     *
     * @param bPaper 试卷
     * @return 结果
     */
    @Override
    public int updateBPaper(BPaper bPaper) {
        return bPaperMapper.updateBPaper(bPaper);
    }

    /**
     * 批量删除试卷
     *
     * @param paperIds 需要删除的试卷主键
     * @return 结果
     */
    @Override
    public int deleteBPaperByPaperIds(Long[] paperIds) {
        return bPaperMapper.deleteBPaperByPaperIds(paperIds);
    }

    /**
     * 删除试卷信息
     *
     * @param paperId 试卷主键
     * @return 结果
     */
    @Override
    public int deleteBPaperByPaperId(Long paperId) {
        return bPaperMapper.deleteBPaperByPaperId(paperId);
    }

    @Override
    public int buildBPaperByPaperIds(Long[] paperIds) throws Exception {
        int n = 0;
        for (Long id : paperIds) {
            BPaper bPaper = selectBPaperByPaperId(id);
            BTopic bTopic = new BTopic();
            bTopic.setPaperId(id);
            if (topicService.selectBTopicList(bTopic).size() > 0) {
                throw new Exception(StringUtils.format("试卷（{}）已经生成，无需再次生成。 ", bPaper.getName()));
            }
            List<BBank> bBanks = new ArrayList<>();
            BBank bBank = new BBank();
            bBank.setSubject(bPaper.getSubject());
            for (String grade : bPaper.getGrade().split(",")) {
                bBank.setGrade(grade);
                bBanks.addAll(bBankService.selectBBankList(bBank));
            }
            Map<String, List<BBank>> collect = bBanks.stream().collect(Collectors.groupingBy(BBank::getQuestionType));
            if ((bPaper.getMustFillNum() + bPaper.getLootFillNum()) > collect.get("1").size()) {
                throw new Exception(StringUtils.format("题库中填空题数量不足，无法生成。"));
            }
            if ((bPaper.getMustChoiceNum() + bPaper.getLootChoiceNum()) > collect.get("2").size()) {
                throw new Exception(StringUtils.format("题库中选择题数量不足，无法生成。"));
            }
            if ((bPaper.getMustSayNum() + bPaper.getLootSayNum()) > collect.get("3").size()) {
                throw new Exception(StringUtils.format("题库中背诵题数量不足，无法生成。"));
            }
            if ((bPaper.getMustExplainNum() + bPaper.getLootExplainNum()) > collect.get("4").size()) {
                throw new Exception(StringUtils.format("题库中赏析题数量不足，无法生成。"));
            }
            Long number = 1L;
            number = buildTopic(collect, bTopic, number, "1", bPaper.getMustFillNum(), bPaper.getLootFillNum());
            number = buildTopic(collect, bTopic, number, "2", bPaper.getMustChoiceNum(), bPaper.getLootChoiceNum());
            number = buildTopic(collect, bTopic, number, "3", bPaper.getMustSayNum(), bPaper.getLootSayNum());
            number = buildTopic(collect, bTopic, number, "4", bPaper.getMustExplainNum(), bPaper.getLootExplainNum());
            n += number;
        }
        return n;
    }

    private Long buildTopic(Map<String, List<BBank>> collect, BTopic bTopic, Long number, String questionType, int mustNum, int lootNum) {
        int[] nums = getUniqueRandomNumbers(collect.get(questionType).size(), mustNum + lootNum);
        for (int i = 0; i < nums.length; i++) {
            BBank bBank = collect.get(questionType).get(i);
            BeanUtils.copyProperties(bBank, bTopic);
            bTopic.setAnswerType(i < mustNum ? "1" : "2");
            bTopic.setNumber(number);
            bTopicService.insertBTopic(bTopic);
            number++;
        }
        return number;
    }

    public static int[] getUniqueRandomNumbers(int upperBound, int count) {
        Random random = new Random();
        Set<Integer> numbers = new HashSet<>();
        while (numbers.size() < count) {
            int randomNumber = random.nextInt(upperBound);
            numbers.add(randomNumber);
        }
        int[] result = new int[numbers.size()];
        int index = 0;
        for (int number : numbers) {
            result[index++] = number;
        }
        return result;
    }
}
